package thread;

import java.util.Scanner;

/**
 * @User: vitobo
 * @Date: 2024-07-31
 * @Description:  volatile关键字
 *
 * 内存可见性问题:
 *    一个线程针对一个变量进行读取操作， 同时另一个线程针对这个变量进行修改，此时读到的值，不一定是修改之后的值
 *
 */

class MyCounter{
    //public int flag = 0;
    // 加上volatile关键字,告诉编译器，这个变量是“易变的”；
    volatile public int flag = 0;
}
public class ThreadDemo15 {

    // 编译器的优化, 很多时候是"玄学问题", 应用程序这个角度是无法感知的;
    // 因此稳妥的做法, 还是把该加volatile的地方都给加上;

    // 加上sleep之后, 控制了循环的速度, 即使不加volatile关键字,代码也正确执行了(刚才错误的优化也消失了)
    public static void main(String[] args) {
        MyCounter myCounter = new MyCounter();

        // t1线程进行读
        Thread t1 = new Thread(()->{
            while (myCounter.flag == 0){
                // ...
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
            System.out.println("t1 循环结束");
        });

        // t2线程进行修改
        Thread t2 = new Thread(()->{
            Scanner scanner = new Scanner(System.in);
            System.out.println("请输入一个数字: ");
            myCounter.flag = scanner.nextInt();
        });

        t1.start();
        t2.start();
    }
    public static void main1(String[] args) {
        MyCounter myCounter = new MyCounter();

        // t1线程进行读
        Thread t1 = new Thread(()->{
            while (myCounter.flag == 0){
                // ...
            }
            System.out.println("t1 循环结束");
        });

        // t2线程进行修改
        Thread t2 = new Thread(()->{
            Scanner scanner = new Scanner(System.in);
            System.out.println("请输入一个数字: ");
            myCounter.flag = scanner.nextInt();
        });

        t1.start();
        t2.start();


    }
}
